package com.example.recording.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.example.recording.R;


public class TimerView extends View {
    private static final String DEFAULT_COLOR = "#0079FE";
    private static final String DEFAULT_TEXT_COLOR = "#FFFFFF";
    private static final String DEFAULT_BG_PROGRESS_COLOR = "#CCCCCC";
    private static final int DEFAULT_RADIUS = 100;
    private static final int DEFAULT_MAX_DURATION = 60 * 1000;

    private static final int DRAW_START_ANGLE = 225;
    private static final int DRAW_MAX_SWEEP_ANGLE = -340;

    private int radius;
    private Paint paint;
    private Paint textPaint;
    private int bgProgressColor;
    private int color;
    private int width;
    private int height;
    private long duration = 0;
    private int maxDuration;
    private long startTime;
    private boolean isStartTimer = false;

    private OnTimerListener onTimerListener;

    public TimerView(Context context) {
        this(context, null);
    }

    public TimerView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TimerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(attrs);
    }

    private void initView(AttributeSet attrs) {
        TypedArray attributes = getContext().obtainStyledAttributes(attrs, R.styleable.TimerView);
        color = attributes.getColor(R.styleable.TimerView_color, Color.parseColor(DEFAULT_COLOR));
        radius = (int) attributes.getDimension(R.styleable.TimerView_radius, dip2px(DEFAULT_RADIUS));
        int textColor = attributes.getColor(R.styleable.TimerView_textColor, Color.parseColor(DEFAULT_TEXT_COLOR));
        bgProgressColor = attributes.getColor(R.styleable.TimerView_bgProgressColor, Color.parseColor(DEFAULT_BG_PROGRESS_COLOR));
        float textSize = attributes.getDimension(R.styleable.TimerView_textSize, radius / 4);
        maxDuration = attributes.getInteger(R.styleable.TimerView_maxDuration, DEFAULT_MAX_DURATION);
        attributes.recycle();

        paint = new Paint();
        paint.setColor(color);
        paint.setAntiAlias(true);
        paint.setStrokeCap(Paint.Cap.ROUND);

        textPaint = new Paint();
        textPaint.setColor(textColor);
        textPaint.setTextSize(textSize);
        textPaint.setAntiAlias(true);
        Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD);
        textPaint.setTypeface(font);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measureSize(widthMeasureSpec),
                measureSize(heightMeasureSpec));
        width = getMeasuredWidth();
        height = getMeasuredHeight();
    }

    private int measureSize(int measureSpec) {
        int result;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
            result = radius * 2 + getPaddingLeft() + getPaddingRight();
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        return result;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        calcTime();
        drawTime(canvas);
        drawProgress(canvas);
        super.onDraw(canvas);
    }

    private void drawProgress(Canvas canvas) {
        paint.setStyle(Paint.Style.STROKE);
        int strokeWidth = radius / 6;
        paint.setStrokeWidth(strokeWidth);
        int offset = strokeWidth / 2;
        RectF rectF = new RectF(offset, offset, width - offset, height - offset);
        paint.setColor(bgProgressColor);
        canvas.drawArc(rectF, DRAW_START_ANGLE, DRAW_MAX_SWEEP_ANGLE, false, paint);
        paint.setColor(color);
        float sweepAngle = 1.0f * duration / maxDuration * DRAW_MAX_SWEEP_ANGLE;
        canvas.drawArc(rectF, DRAW_START_ANGLE, sweepAngle, false, paint);
    }

    private void drawTime(Canvas canvas) {
        paint.setStyle(Paint.Style.FILL);
        canvas.drawCircle(width / 2, height / 2, radius / 2, paint);
        String timeText = getTimeText();
        Rect rect = new Rect();
        textPaint.getTextBounds(timeText, 0, timeText.length(), rect);
        canvas.drawText(timeText, (width - rect.width()) / 2, (height + rect.height()) / 2, textPaint);
    }


    private String getTimeText() {
        long durationUnitSecond = duration / 1000;
        long minute = durationUnitSecond / 60;
        long second = durationUnitSecond % 60;
        return String.format("%s:%s", minute > 9 ? minute : "0" + minute, second > 9 ? second : "0" + second);
    }

    private int dip2px(float dpValue) {
        final float scale = getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    private void calcTime() {
        if (!isStartTimer)
            return;
        duration = System.currentTimeMillis() - startTime;
        if (duration <= maxDuration) {
            postInvalidate();
        } else {
            stop();
        }
    }

    public void start() {
        startTime = System.currentTimeMillis() - duration;
        isStartTimer = true;
        postInvalidate();
        if (onTimerListener != null) {
            onTimerListener.onStartTimer(startTime);
        }
    }

    public void stop() {
        isStartTimer = false;
        if (onTimerListener != null) {
            onTimerListener.onStopTimer(duration);
        }
    }

    public void clean() {
        isStartTimer = false;
        duration = 0;
        startTime = 0;
        postInvalidate();
        if (onTimerListener != null) {
            onTimerListener.onCleanTimer();
        }
    }


    public interface OnTimerListener {
        void onStartTimer(long startTime);

        void onStopTimer(long duration);

        void onCleanTimer();
    }

    public void setOnTimerListener(OnTimerListener onTimerListener) {
        this.onTimerListener = onTimerListener;
    }

}
